param(
    [string]$Path = ".",
    [string]$SearchPattern = "*.csproj",
    [string]$Configuration = "Release",
    [string]$OutputDirBase = "./artifacts/nupkg",
    [string]$ApiKey = "oy2lgftmv4ohkgwiqluqohx77uurgowupe7lqszmptejnu",
    [string]$NuGetSource = "https://api.nuget.org/v3/index.json",
    [switch]$PackOnly,
    [switch]$PushOnly,
    [string]$VersionSuffix = "",
    [switch]$cleanOutput
)

$ErrorActionPreference = "Stop"

# 设置控制台输出编码为UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# 彩色输出函数
function Write-Header ($message) {
    Write-Host "`n" + ("="*80) -ForegroundColor Cyan
    Write-Host $message -ForegroundColor Cyan
    Write-Host ("="*80) -ForegroundColor Cyan
}

function Write-Success ($message) {
    Write-Host $message -ForegroundColor Green
}

function Write-Info ($message) {
    Write-Host $message -ForegroundColor Yellow
}

function Write-ErrorMsg ($message) {
    Write-Host $message -ForegroundColor Red
}

# 验证API密钥
function Get-ValidApiKey {
    if (-not $ApiKey) {
        $envApiKey = $env:NUGET_API_KEY
        if (-not $envApiKey) {
            Throw "Can not Found API Key! Please Use:`n1. -ApiKey Option`n2. NUGET_API_KEY Environment Variable"
        }
        return $ApiKey
    }
    return $ApiKey
}

# 验证.NET SDK
function Test-DotnetSdk {
    try {
        $sdkVersion = dotnet --version
        Write-Info "Check .NET SDK Version: $sdkVersion"
    }
    catch {
        Throw "Not Found dotnet command! Please Install .NET SDK: https://dotnet.microsoft.com/download"
    }
    
    # 验证是否为.NET 9 SDK
    $requiredVersion = "9.0"
    if (-not $sdkVersion.StartsWith($requiredVersion)) {
        Write-Info "Warning: Current SDK Version($sdkVersion) is not.NET 9, But Contiune"
    }
}

# 查找项目文件
function Find-ProjectFiles {
    param(
        [string]$searchPath,
        [string]$pattern
    )
    
    $projects = Get-ChildItem -Path $searchPath -Filter $pattern -Recurse -File
    
    if (-not $projects) {
        Throw "In '$searchPath' Can not found '$pattern' Project File"
    }
    
    Write-Info "Found $($projects.Count) of Project:"
    $projects | ForEach-Object { Write-Info "  - $($_.FullName)" }
    
    return $projects
}

# 打包项目
function Invoke-PackProject {
    param(
        [System.IO.FileInfo]$project,
        [string]$config,
        [string]$outputRoot,
        [string]$versionSuffix,
        [bool]$cleanOutput
        )
    
    $projectName = $project.BaseName
    $outputDir = Join-Path $outputRoot $projectName
    
    # 清理输出目录
    if ($cleanOutput -and (Test-Path $outputDir)) {
        Remove-Item $outputDir -Recurse -Force -ErrorAction SilentlyContinue
    }
    
    if (-not (Test-Path $outputDir)) {
        New-Item -ItemType Directory -Path $outputDir | Out-Null
    }
    
    # 构建打包参数
    $packArgs = @("pack",$project.FullName,"-c", $config,"-o", $outputDir,"--nologo","--verbosity", "minimal")
    
    if (-not [string]::IsNullOrWhiteSpace($versionSuffix)) {
        $packArgs += "--version-suffix"
        $packArgs += $versionSuffix
    }
    
    Write-Info "`nPack Project: $projectName"
    Write-Info "Output Directory: $outputDir"
    
    & dotnet $packArgs

    if ($LASTEXITCODE -ne 0) {
        Throw "Project '$projectName' Pack Failed"
    }
}

function Invoke-PushPackage {
    param(
        [System.IO.FileInfo]$package,
        [string]$apiKey,
        [string]$source
    )
    $packageName = $package.Name
    Write-Info "Push Package: $packageName"
    $pushArgs = @("nuget", "push",$package.FullName,"--api-key", $apiKey,"--source", $source,"--skip-duplicate")
    & dotnet $pushArgs

    if ($LASTEXITCODE -ne 0) {
        Throw "Package '$packageName' Push Failed"
    }
    
    Write-Success "Package Push Success: $packageName"
}

# ============================================================
# 主脚本执行流程
# ============================================================

try{
    Write-Header "Batch .NET NuGet Package Publishing Tool | Supports .NET 9"
    $validApiKey = Get-ValidApiKey
    Test-DotnetSdk
    $projectFiles = Find-ProjectFiles -searchPath $Path -pattern $SearchPattern
    
    if (-not $PushOnly){
        Write-Header "Phase 1: Batch Packaging of Projects"
        foreach ($project in $projectFiles){
            try{
                Invoke-PackProject -project $project `
                    -config $Configuration `
                    -outputRoot $OutputDirBase `
                    -versionSuffix $VersionSuffix `
                    -cleanOutput $cleanOutput
            }
            catch{
                Write-ErrorMsg "Error: $($_.Exception.Message)"
                Write-Info "Skip Project $($project.Name)"
            }
        }
    }
    
    if (-not $PackOnly){
        Write-Header "Phase 2: Batch Push Packages to NuGet"
        
        $allPackages = Get-ChildItem -Path $OutputDirBase -Filter "*.nupkg" -Recurse
        if (-not $allPackages) {
            Throw "No package files found to push! Check the directory: $OutputDirBase"
        }
        
        Write-Info "Found $($allPackages.Count) package files"
        foreach ($package in $allPackages) {
            try {
                Invoke-PushPackage -package $package -apiKey $validApiKey -source $NuGetSource
            }
            catch {
                Write-ErrorMsg "Error: $($_.Exception.Message)"
                Write-Info "Skip Package $($package.Name)"
            }
        }
    }
    
    Write-Header "Operation complete!"
    Write-Success "Successfully processed packages: $($allPackages.Count)"
    Write-Success "View Published Packages: https://www.nuget.org/packages/manage/uploaded"
}
catch {
    Write-ErrorMsg "`nCritical Error: $($_.Exception.Message)"
    exit 1
}